<template>
  <div class="subform">
    <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
      <div>
        <div class="row-head">
          <div class="head-label">
            <span>&nbsp;</span>
          </div>
          <div class="row-num">
            1
          </div>
        </div>
        <div v-if="drawingList.length == 0" class="placehold">
          <span>从左侧拖拽来添加字段</span>
        </div>
        <div v-else class="subformItem scrollbox">
          <div :style="{width: drawingList.length * 175 + 'px', minWidth: '100%'}" class="subformScroll">
            <draggable-item
              v-for="(item, index) in drawingList"
              :style="{position: 'absolute', left: index * 175 + 'px'}"
              :key="item.renderKey"
              :drawing-list="drawingList"
              :current-item="item"
              :index="index"
              :active-id="activeId"
              :form-conf="formConf"
              @activeItem="activeFormItem"
              @copyItem="drawingItemCopy"
              @deleteItem="drawingItemDelete"
            />
          </div>
        </div>
      </div>
    </draggable>
  </div>
</template>
<script>
import draggable from 'vuedraggable'
import { debounce } from 'throttle-debounce'
import {
  inputComponents, selectComponents, layoutComponents, formConf
} from '@/components/generator/config'
import { titleCase, deepClone, isObjectObject } from '@/utils/index'
import drawingDefalut from '@/components/generator/drawingDefalut'
import DraggableItem from './subDraggableItem'
import {
  getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
} from '@/utils/db'

let oldActiveId
let tempActiveData
const drawingListInDB = getDrawingList()
const formConfInDB = getFormConf()
const idGlobal = getIdGlobal()

export default {
  name: 'Subform',
  components: {
    draggable,
    DraggableItem
  },
  props: {
    conf: {
      type: Object,
      required: false
    }
  },
  data() {
    return {
      activeIndex: '1',
      navName: '表单名称',
      idGlobal,
      formConf,
      inputComponents,
      selectComponents,
      layoutComponents,
      labelWidth: 100,
      drawingList: [],
      drawingData: {},
      activeId: null,
      drawerVisible: false,
      formData: {},
      dialogVisible: false,
      jsonDrawerVisible: false,
      generateConf: null,
      showFileName: false,
      activeData: '',
      saveDrawingListDebounce: debounce(340, saveDrawingList),
      saveIdGlobalDebounce: debounce(340, saveIdGlobal),
      formshow: false,
      tableData: [{
        date: ''
      }]
    }
  },
  watch: {
    // eslint-disable-next-line func-names
    'activeData.__config__.label': function (val, oldVal) {
      if (
        this.activeData.placeholder === undefined
        || !this.activeData.__config__.tag
        || oldActiveId !== this.activeId
      ) {
        return
      }
      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
    },
    activeId: {
      handler(val) {
        oldActiveId = val
      },
      immediate: true
    },
    drawingList: {
      handler(newVal) {
        console.log(this.$parent._props.conf)
        this.$store.commit('design/SET_SUBFORMINFO', {value: newVal, formId: this.$parent._props.conf.__config__.formId})
        this.$store.commit('design/SET_SUBFORMFLAG', new Date().getTime())
      },
      deep: true
    },
    idGlobal: {
      handler(val) {
        this.saveIdGlobalDebounce(val)
      },
      immediate: true
    }
  },
  methods: {
    setObjectValueReduce(obj, strKeys, data) {
      const arr = strKeys.split('.')
      arr.reduce((pre, item, i) => {
        if (arr.length === i + 1) {
          pre[item] = data
        } else if (!isObjectObject(pre[item])) {
          pre[item] = {}
        }
        return pre[item]
      }, obj)
    },
    setRespData(component, resp) {
      const { dataPath, renderKey, dataConsumer } = component.__config__
      if (!dataPath || !dataConsumer) return
      const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)

      // 将请求回来的数据，赋值到指定属性。
      // 以el-tabel为例，根据Element文档，应该将数据赋值给el-tabel的data属性，所以dataConsumer的值应为'data';
      // 此时赋值代码可写成 component[dataConsumer] = respData；
      // 但为支持更深层级的赋值（如：dataConsumer的值为'options.data'）,使用setObjectValueReduce
      this.setObjectValueReduce(component, dataConsumer, respData)
      const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
      if (i > -1) this.$set(this.drawingList, i, component)
    },
    fetchData(component) {
      const { dataType, method, url } = component.__config__
      if (dataType === 'dynamic' && method && url) {
        this.setLoading(component, true)
        this.$axios({
          method,
          url
        }).then(resp => {
          this.setLoading(component, false)
          this.setRespData(component, resp.data)
        })
      }
    },
    setLoading(component, val) {
      const { directives } = component
      if (Array.isArray(directives)) {
        const t = directives.find(d => d.name === 'loading')
        if (t) t.value = val
      }
    },
    activeFormItem(currentItem) {
      this.$store.commit('design/SET_SUBFORMACTIVEID', currentItem)      
      this.activeData = currentItem
      this.activeId = currentItem.__config__.formId
    },
    onEnd(obj) {
      if (obj.from !== obj.to) {
        this.fetchData(tempActiveData)
        this.activeData = tempActiveData
        this.activeId = this.idGlobal
      }
    },
    addComponent(item) {
      const clone = this.cloneComponent(item)
      this.fetchData(clone)
      this.drawingList.push(clone)
      this.activeFormItem(clone)
    },
    cloneComponent(origin) {
      const clone = deepClone(origin)
      const config = clone.__config__
      config.span = this.formConf.span // 生成代码时，会根据span做精简判断
      this.createIdAndKey(clone)
      clone.placeholder !== undefined && (clone.placeholder += config.label)
      tempActiveData = clone
      return tempActiveData
    },
    createIdAndKey(item) {
      const config = item.__config__
      config.formId = ++this.idGlobal
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
      if (config.layout === 'colFormItem') {
        item.__vModel__ = `field${this.idGlobal}`
      } else if (config.layout === 'rowFormItem') {
        config.componentName = `row${this.idGlobal}`
        !Array.isArray(config.children) && (config.children = [])
        delete config.label // rowFormItem无需配置label属性
      }
      if (Array.isArray(config.children)) {
        config.children = config.children.map(childItem => this.createIdAndKey(childItem))
      }
      return item
    },
    AssembleFormData() {
      this.formData = {
        fields: deepClone(this.drawingList),
        ...this.formConf
      }
    },
    generate(data) {
      const func = this[`exec${titleCase(this.operationType)}`]
      console.log(func)
      this.generateConf = data
      func && func(data)
    },
    execRun(data) {
      this.AssembleFormData()
      this.drawerVisible = true
    },
    execCopy(data) {
      document.getElementById('copyNode').click()
    },
    empty() {
      this.$confirm('确定要清空所有组件吗？', '提示', { type: 'warning' }).then(
        () => {
          this.drawingList = []
          this.idGlobal = 100
        }
      )
    },
    drawingItemCopy(item, list) {
      console.log('drawingItemCopy')
      console.log(item)
      console.log(list)
      let clone = deepClone(item)
      clone = this.createIdAndKey(clone)
      list.push(clone)
      this.activeFormItem(clone)
    },
    drawingItemDelete(index, list) {
      list.splice(index, 1)
      this.$nextTick(() => {
        const len = this.drawingList.length
        if (len) {
          this.activeFormItem(this.drawingList[len - 1])
        }
      })
    },
    showJson() {
      this.AssembleFormData()
      this.jsonDrawerVisible = true
    },
    download() {
      this.dialogVisible = true
      this.showFileName = true
      this.operationType = 'download'
    },
    run() {
      this.dialogVisible = true
      this.showFileName = false
      this.operationType = 'run'
    },
    copy() {
      this.dialogVisible = true
      this.showFileName = false
      this.operationType = 'copy'
    },
    tagChange(newTag) {
      newTag = this.cloneComponent(newTag)
      const config = newTag.__config__
      newTag.__vModel__ = this.activeData.__vModel__
      config.formId = this.activeId
      config.span = this.activeData.__config__.span
      this.activeData.__config__.tag = config.tag
      this.activeData.__config__.tagIcon = config.tagIcon
      this.activeData.__config__.document = config.document
      if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
        config.defaultValue = this.activeData.__config__.defaultValue
      }
      Object.keys(newTag).forEach(key => {
        if (this.activeData[key] !== undefined) {
          newTag[key] = this.activeData[key]
        }
      })
      this.activeData = newTag
      this.updateDrawingList(newTag, this.drawingList)
    },
    updateDrawingList(newTag, list) {
      const index = list.findIndex(item => item.__config__.formId === this.activeId)
      if (index > -1) {
        list.splice(index, 1, newTag)
      } else {
        list.forEach(item => {
          if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
        })
      }
    },
    refreshJson(data) {
      this.drawingList = deepClone(data.fields)
      delete data.fields
      this.formConf = data
    }
  }
}
</script>
<style lang='scss'>
.subform {
  .row-head {
      width: 68px;
      padding-bottom: 28px;
  }
  .row-head .head-label {
      background: #fff;
      width: 68px;
      height: 35px;
      border: 1px solid #eee;
      border-top-left-radius: 3px;
  }
  .form-design-subform.one-line .row-head .row-num {
      height: 40px;
      line-height: 40px;
  }
  .row-head .row-num:last-child {
      border-bottom: solid 1px #eee;
      border-bottom-left-radius: 3px;
  }
  .row-head .row-num {
      position: relative;
      width: 68px;
      height: 40px;
      line-height: 40px;
      text-align: center;
      background: #fcfcfd;
      border-left: solid 1px #eee;
      border-right: solid 1px #eee;
  }
  .placehold {
    position:absolute;
    top: 0;
    left: 68px;
    bottom: 0;
    right: 0;
    display: flex;
    height: 76px;
    margin: 0 auto;
    border: solid 1px #eee;
    border-left: none;
  }
  .placehold span {
    color: #ccc;
    padding: 0 10px;
  }
  .subformItem {
      position: absolute;
      top: 0;
      left: 68px;
      width: 100%;
      height: 78px;
      overflow-x: scroll;
  }
  .row-head-item {
    float: left;
  }
  .head-labe-item {
    border-top: 1px solid #eee;
    border-bottom: 1px solid #eee;
    border-right: 1px solid #eee;
    line-height: 35px;
  }
  .row-num-item {
    border-right: 1px solid #eee;
    border-bottom: 1px solid #eee;
    line-height: 40px;
  }
  .scrollbox {
    height: 100%;
    width: 100%;
    overflow: auto;
    // 滚动条整体部分
    &::-webkit-scrollbar{
        width: 6px;//对垂直方向滚动条
        height: 6px;//对水平方向滚动条
    }
    //滚动的滑块
    &::-webkit-scrollbar-thumb{
    border-radius:3px;
    background-color: #ccc//滚动条的颜色
    }
  }
  .drawing-item-copy, .drawing-item-delete {
    top: 0px!important;
  }
  .subFormItemWidth {
    width: 175px;
  }
}
</style>
